package cn.com.generaldata.os.service.indicator_evaluation.gop_forecast;

import java.math.BigDecimal;

import jsme_matlab.Calculate;

import org.nutz.dao.Chain;
import org.nutz.dao.Cnd;
import org.nutz.dao.Dao;
import org.nutz.dao.sql.Criteria;
import org.nutz.lang.random.R;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import cn.com.generaldata.jsme_indicator_system.entity.IndicatorEvaluation;
import cn.com.generaldata.os.pojo.IndicatorEvaluationResult;
import cn.com.generaldata.os.service.indicator_constant.ProvinceIndicatorConstant;
import cn.com.generaldata.os.service.indicator_evaluation.CalculateService;
import cn.com.generaldata.os.service.indicator_evaluation.CalculateServiceHelper;
import cn.com.generaldata.os.util.BeanMapper;
import cn.com.generaldata.os.vo.IndicatorAccountVO;

import com.mathworks.toolbox.javabuilder.MWException;
import com.mathworks.toolbox.javabuilder.MWNumericArray;

/**
 * 回归预测评估指标计算类.
 */
public class RegressionGOPCalculateService implements CalculateService {

	private String GOPIndicatorName = ProvinceIndicatorConstant.GOP_INDICATOR_NAME;

	private Dao dao;

	private Dao indicatorSystemDao;

	private static final Integer year = 2001;

	private static Logger log = LoggerFactory.getLogger(RegressionGOPCalculateService.class);

	private CalculateServiceHelper helper;

	@Override
	public void calculateIndicator(IndicatorEvaluation indicator, IndicatorAccountVO indicatorAccountVO) {

		double[][] gops = getData(indicatorAccountVO, GOPIndicatorName);
		double[][] totalRetailSales = getData(indicatorAccountVO, "消费品零售总额");
		double[][] fiscalExpenditure = getData(indicatorAccountVO, "财政支出");
		double[][] consumerPriceIndex = getData(indicatorAccountVO, "居民消费价格指数");

		Calculate cal = null;
		try {
			cal = new Calculate();
			Object[] result = cal.huigui2(2, gops, totalRetailSales, fiscalExpenditure, consumerPriceIndex);

			MWNumericArray r = (MWNumericArray) result[1];
			double[] doubleData = r.getDoubleData();
			if (doubleData != null && doubleData.length != 0) {
				Criteria cri = Cnd.cri();
				cri.where().and("indicator_id", "=", indicator.getId());
				cri.where().and("area_id", "=", indicatorAccountVO.getAreaId());
				cri.where().and("time_type", "=", indicatorAccountVO.getTimeType());
				dao.clear("tbl_indicator_evaluation_res", cri);

				int startYear = year + 1;
				for (int i = 0, length = doubleData.length; i < length; i++) {

					IndicatorAccountVO vo = BeanMapper.map(indicatorAccountVO, IndicatorAccountVO.class);
					vo.setYear(startYear + i);
					IndicatorEvaluationResult ier = new IndicatorEvaluationResult();
					BeanMapper.copy(vo, ier);
					ier.setIndicatorId(indicator.getId());
					BigDecimal bg = new BigDecimal(doubleData[i]);
					Double data = bg.setScale(10, BigDecimal.ROUND_HALF_UP).doubleValue();
					ier.setIndicatorValue(data);

					saveIndicatorEvaluationResult(ier);
				}
			}
		} catch (MWException e) {
			log.error("调用Matlab计算回归预测趋势预测指标错误", e);
		} finally {
			if (cal != null) {
				cal.dispose();
			}
		}
	}

	/**
	 * 获取江苏消费品零售总额
	 * 
	 * @param indicatorAccountVO
	 * @return
	 */
	private double[][] getData(IndicatorAccountVO indicatorAccountVO, String indicatorName) {
		// 输入年份
		Integer nowYear = indicatorAccountVO.getYear();
		double[][] data = new double[nowYear - year + 1][1];
		int i = year;
		// 获取定基年份到所查年份上一年的
		for (; i <= nowYear; i++) {
			IndicatorAccountVO accountVO = BeanMapper.map(indicatorAccountVO, IndicatorAccountVO.class);
			accountVO.setYear(i);
			Double result = helper.getInputOrAccountingIndicatorValue(accountVO, i, indicatorName);
			if (result == null) {
				break;
			}
			data[i - year][0] = result;
		}
		double[][] dataNew = new double[i - year][1];
		for (int y = 0, length = i - year; y < length; y++) {
			dataNew[y][0] = data[y][0];
		}

		return dataNew;
	}

	private void saveIndicatorEvaluationResult(IndicatorEvaluationResult ier) {
		// 保存新记录
		Chain chain = Chain.make("id", R.UU16());
		chain.add("indicator_id", ier.getIndicatorId());
		chain.add("area_id", ier.getAreaId());
		chain.add("year", ier.getYear());
		chain.add("time_type", ier.getTimeType());
		chain.add("year_time", ier.getYearTime());
		chain.add("indicator_value", ier.getIndicatorValue());

		dao.insert("tbl_indicator_evaluation_res", chain);
	}

	@Override
	public void setDao(Dao dao) {
		this.dao = dao;
	}

	@Override
	public void setIndicatorSystemDao(Dao indicatorSystemDao) {
		this.indicatorSystemDao = indicatorSystemDao;
	}

	@Override
	public void setCalculateServiceHelper(CalculateServiceHelper calculateServiceHelper) {
		helper = calculateServiceHelper;
	}

}
